package com.gmall.search.listener;

import com.gmall.common.bean.ResponseVo;
import com.gmall.pms.entity.*;
import com.gmall.search.feign.GmallPmsClient;
import com.gmall.search.feign.GmallWmsClient;
import com.gmall.search.pojo.Goods;
import com.gmall.search.pojo.SearchAttrValueVo;
import com.gmall.wms.entity.WareSkuEntity;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: liush
 * @CreateTime: 2023-05-16  18:34
 * @Description: TODO
 */
@Component
public class GoodsListener {

    @Autowired
    private GmallPmsClient pmsClient;

    @Autowired
    private GmallWmsClient wmsClient;

    @Autowired
    private ElasticsearchRestTemplate restTemplate;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue("search.insert.queue"),
            exchange = @Exchange(value = "pms.spu.exchange", type = ExchangeTypes.TOPIC, ignoreDeclarationExceptions = "true"),
            key = {"item.insert"}
    ))
    public void listener(Long spuId, Channel channel, Message message) throws IOException {
        if (spuId == null) {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }

        // 根据spuid查询spu
        ResponseVo<SpuEntity> spuEntityResponseVo = this.pmsClient.querySpuById(spuId);
        SpuEntity spuEntity = spuEntityResponseVo.getData();
        if (spuEntity == null) {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }

        ResponseVo<List<SkuEntity>> skuResponseVo = this.pmsClient.querySkuBySpuId(spuEntity.getId());
        List<SkuEntity> skuEntities = skuResponseVo.getData();

        // 如果当前spu下的sku为空，则直接continue
        if (CollectionUtils.isEmpty(skuEntities)) {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }

        // 查询品牌 因为品牌和分类 只要是同一个spu一定是相同的
        ResponseVo<BrandEntity> brandEntityResponseVo = this.pmsClient.queryBrandById(spuEntity.getBrandId());
        BrandEntity brandEntity = brandEntityResponseVo.getData();

        // 查询分类
        ResponseVo<CategoryEntity> categoryEntityResponseVo = this.pmsClient.queryCategoryById(spuEntity.getCategoryId());
        CategoryEntity categoryEntity = categoryEntityResponseVo.getData();

        // 基本类型的检索属性和值
        ResponseVo<List<SpuAttrValueEntity>> baseAttrValueResponseVo = this.pmsClient.querySearchAttrValueByCidAndSpuId(spuEntity.getCategoryId(), spuEntity.getId());
        List<SpuAttrValueEntity> spuAttrValueEntities = baseAttrValueResponseVo.getData();

        // 3.把sku集合转成goods集合
        this.restTemplate.save(skuEntities.stream().map(skuEntity -> {
            Goods goods = new Goods();
            // 设置sku相关字段
            goods.setSkuId(skuEntity.getId());
            goods.setTitle(skuEntity.getTitle());
            goods.setSubtitle(skuEntity.getSubtitle());
            goods.setDefaultImage(skuEntity.getDefaultImage());
            goods.setPrice(skuEntity.getPrice().doubleValue());

            // 设置createTime
            goods.setCreateTime(spuEntity.getCreateTime());

            // 根据skuId查询库存
            ResponseVo<List<WareSkuEntity>> wareResponseVo = this.wmsClient.queryWareSkuBySkuId(skuEntity.getId());
            List<WareSkuEntity> wareSkuEntities = wareResponseVo.getData();
            if (!CollectionUtils.isEmpty(wareSkuEntities)) {
                goods.setSales(wareSkuEntities.stream().map(WareSkuEntity::getSales).reduce((a, b) -> a + b).get());
                goods.setStore(wareSkuEntities.stream().anyMatch(wareSkuEntity -> wareSkuEntity.getStock() - wareSkuEntity.getStockLocked() > 0));
            }

            // 设置品牌参数
            if (brandEntity != null) {
                goods.setBrandId(brandEntity.getId());
                goods.setBrandName(brandEntity.getName());
                goods.setLogo(brandEntity.getLogo());
            }

            // 设置分类参数
            if (categoryEntity != null) {
                goods.setCategoryId(categoryEntity.getId());
                goods.setCategoryName(categoryEntity.getName());
            }

            // 销售类型的检索类型的规格参数
            ResponseVo<List<SkuAttrValueEntity>> saleAttrValueResponseVo = this.pmsClient.querySearchAttrValueByCidAndSkuId(skuEntity.getCategoryId(), skuEntity.getId());
            List<SkuAttrValueEntity> skuAttrValueEntities = saleAttrValueResponseVo.getData();

            // 定义一个vo集合，收集两个entity集合中的数据
            List<SearchAttrValueVo> searchAttrs = new ArrayList<>();
            if (!CollectionUtils.isEmpty(skuAttrValueEntities)) {
                searchAttrs.addAll(skuAttrValueEntities.stream().map(skuAttrValueEntity -> {
                    SearchAttrValueVo searchAttrValueVo = new SearchAttrValueVo();
                    BeanUtils.copyProperties(skuAttrValueEntity, searchAttrValueVo);
                    return searchAttrValueVo;
                }).collect(Collectors.toList()));
            }
            if (!CollectionUtils.isEmpty(spuAttrValueEntities)) {
                searchAttrs.addAll(spuAttrValueEntities.stream().map(spuAttrValueEntity -> {
                    SearchAttrValueVo searchAttrValueVo = new SearchAttrValueVo();
                    BeanUtils.copyProperties(spuAttrValueEntity, searchAttrValueVo);
                    return searchAttrValueVo;
                }).collect(Collectors.toList()));
            }
            goods.setSearchAttrs(searchAttrs);

            return goods;
        }).collect(Collectors.toList()));

        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
}
